<script lang="tsx">
  import { defineComponent, ref, h, compile, computed } from 'vue';
  import { useRoute, useRouter, RouteRecordRaw } from 'vue-router';
  import type { RouteMeta } from 'vue-router';
  import { useAppStore } from '@/store';
  import { listenerRouteChange } from '@/utils/route-listener';
  import { openWindow, regexUrl } from '@/utils';
  import useRouteStore from '@/store/modules/route';
  import { localRouteRecordRaw } from '@/router/routes/types';

  export default defineComponent({
    emit: ['collapse'],
    setup() {
      const appStore = useAppStore();
      const router = useRouter();
      const route = useRoute();
      const menuTree = computed(() => useRouteStore().menuBarRouters);

      // 折叠控制
      const collapsed = computed({
        get() {
          if (appStore.device === 'desktop') return appStore.menuCollapse;
          return false;
        },
        set(value: boolean) {
          appStore.updateSettings({ menuCollapse: value });
        },
      });

      const topMenu = computed(() => appStore.topMenu);
      const openKeys = ref<string[]>([]);
      const selectedKey = ref<string[]>([]);
      // 路径跳转处理
      const goto = (item: RouteRecordRaw) => {
        // Open external link
        // 是否为外链
        console.log(item);
        if (regexUrl.test(item.path)) {
          openWindow(item.path);
          selectedKey.value = [item.name as string];
          return;
        }
        // Eliminate external link side effects
        const { hideInMenu, activeMenu } = item.meta as RouteMeta;
        if (route.name === item.name && !hideInMenu && !activeMenu) {
          selectedKey.value = [item.name as string];
          return;
        }
        // Trigger router change
        router.push({
          name: item.name,
        });
      };
      function hasOneShowingChild(
        menuRoute: localRouteRecordRaw,
        backValue: {
          onlyOneChild?: localRouteRecordRaw;
          noShowingChildren?: boolean;
        }
      ) {
        if (!menuRoute.children) {
          menuRoute.children = [];
        }
        const showingChildren = menuRoute.children.filter((item) => {
          if (item.hidden) {
            return false;
          }
          backValue.onlyOneChild = item;
          return true;
        });

        // When there is only one child router, the child router is displayed by default
        if (showingChildren.length === 1) {
          return true;
        }

        // Show parent if there are no child router to display
        // 无可显示的子级将显示自身
        if (showingChildren.length === 0) {
          backValue.onlyOneChild = {
            ...menuRoute,
          };
          backValue.noShowingChildren = true;
          return true;
        }

        return false;
      }
      const findMenuOpenKeys = (target: string) => {
        const result: string[] = [];
        let isFind = false;
        const backtrack = (item: localRouteRecordRaw, keys: string[]) => {
          if (item.name === target) {
            isFind = true;
            result.push(...keys);
            return;
          }
          if (item.children?.length) {
            item.children.forEach((el) => {
              backtrack(el, [...keys, el.name as string]);
            });
          }
        };
        menuTree.value.forEach((el: localRouteRecordRaw) => {
          if (isFind) return; // Performance optimization
          backtrack(el, [el.name as string]);
        });
        return result;
      };
      listenerRouteChange((newRoute) => {
        const { activeMenu } = newRoute.meta;
        if (activeMenu) {
          const menuOpenKeys = findMenuOpenKeys(
            (activeMenu || newRoute.name) as string
          );

          const keySet = new Set([...menuOpenKeys, ...openKeys.value]);
          openKeys.value = [...keySet];
          selectedKey.value = [
            activeMenu || menuOpenKeys[menuOpenKeys.length - 1],
          ];
        }
      }, true);
      const setCollapse = (val: boolean) => {
        if (appStore.device === 'desktop')
          appStore.updateSettings({ menuCollapse: val });
      };

      const renderSubMenu = () => {
        function travel(_route: localRouteRecordRaw[], nodes = []) {
          if (_route.length) {
            _route.forEach((element) => {
              // This is demo, modify nodes as needed
              if (element.hidden) {
                return;
              }
              const oneValue: {
                onlyOneChild?: localRouteRecordRaw;
                noShowingChildren?: boolean;
              } = {};
              let node;
              if (
                hasOneShowingChild(element, oneValue) &&
                (!oneValue.onlyOneChild?.children?.length ||
                  oneValue.noShowingChildren) &&
                !element.alwaysShow
              ) {
                const icon =
                  oneValue.onlyOneChild?.meta?.icon &&
                  oneValue.onlyOneChild?.meta?.icon !== '#'
                    ? () =>
                        h(compile(`<${oneValue.onlyOneChild?.meta?.icon}/>`))
                    : null;
                node = (
                  <a-menu-item
                    key={oneValue.onlyOneChild?.name}
                    v-slots={{ icon }}
                    onClick={() =>
                      goto(oneValue.onlyOneChild as RouteRecordRaw)
                    }
                  >
                    {oneValue.onlyOneChild?.meta?.title || ''}
                  </a-menu-item>
                );
              } else if (element.children?.length) {
                const icon =
                  element?.meta?.icon && element?.meta?.icon !== '#'
                    ? () => h(compile(`<${element?.meta?.icon}/>`))
                    : null;
                node = (
                  <a-sub-menu
                    key={element?.name}
                    v-slots={{
                      icon,
                      title: () => h(compile(element?.meta?.title || '')),
                    }}
                  >
                    {travel(element?.children)}
                  </a-sub-menu>
                );
              }
              nodes.push(node as never);
            });
          }
          return nodes;
        }
        return travel(menuTree.value);
      };
      return () => (
        <a-menu
          mode={topMenu.value ? 'horizontal' : 'vertical'}
          v-model:collapsed={collapsed.value}
          v-model:open-keys={openKeys.value}
          show-collapse-button={appStore.device !== 'mobile'}
          auto-open={false}
          selected-keys={selectedKey.value}
          auto-open-selected={true}
          level-indent={34}
          style="height: 100%;width:100%;"
          onCollapse={setCollapse}
        >
          {renderSubMenu()}
        </a-menu>
      );
    },
  });
</script>

<style lang="less" scoped>
  :deep(.arco-menu-inner) {
    .arco-menu-inline-header {
      display: flex;
      align-items: center;
    }

    .arco-icon {
      &:not(.arco-icon-down) {
        font-size: 18px;
      }
    }
  }
</style>
